/**
 * 性能优化工具函数
 * 提供防抖、节流、内存清理等功能，避免页面卡死
 */

/**
 * 防抖函数 - 延迟执行，如果在延迟期间再次调用则重新计时
 * @param func 要防抖的函数
 * @param wait 延迟时间（毫秒）
 * @param immediate 是否立即执行第一次
 */
export function debounce<T extends (...args: any[]) => any>(
  func: T,
  wait: number,
  immediate?: boolean
): (...args: Parameters<T>) => void {
  let timeout: ReturnType<typeof setTimeout> | null = null;

  return function executedFunction(...args: Parameters<T>) {
    const later = () => {
      timeout = null;
      if (!immediate) func(...args);
    };

    const callNow = immediate && !timeout;

    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(later, wait);

    if (callNow) func(...args);
  };
}

/**
 * 节流函数 - 限制函数执行频率
 * @param func 要节流的函数
 * @param limit 限制间隔（毫秒）
 */
export function throttle<T extends (...args: any[]) => any>(
  func: T,
  limit: number
): (...args: Parameters<T>) => void {
  let inThrottle: boolean;

  return function executedFunction(...args: Parameters<T>) {
    if (!inThrottle) {
      func(...args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

/**
 * 内存清理工具 - 清理可能泄露的事件监听器和定时器
 */
export class MemoryManager {
  private static timers: Set<ReturnType<typeof setTimeout>> = new Set();
  private static intervals: Set<ReturnType<typeof setInterval>> = new Set();
  private static listeners: Map<EventTarget, { event: string; handler: EventListener }[]> = new Map();

  /**
   * 安全的setTimeout，会自动追踪和清理
   */
  static setTimeout(callback: () => void, delay: number): ReturnType<typeof setTimeout> {
    const timer = setTimeout(() => {
      this.timers.delete(timer);
      callback();
    }, delay);

    this.timers.add(timer);
    return timer;
  }

  /**
   * 安全的setInterval，会自动追踪和清理
   */
  static setInterval(callback: () => void, delay: number): ReturnType<typeof setInterval> {
    const interval = setInterval(callback, delay);
    this.intervals.add(interval);
    return interval;
  }

  /**
   * 安全的事件监听器添加，会自动追踪
   */
  static addEventListener(
    target: EventTarget,
    event: string,
    handler: EventListener,
    options?: boolean | AddEventListenerOptions
  ): void {
    target.addEventListener(event, handler, options);

    if (!this.listeners.has(target)) {
      this.listeners.set(target, []);
    }
    this.listeners.get(target)!.push({ event, handler });
  }

  /**
   * 清理指定的定时器
   */
  static clearTimeout(timer: ReturnType<typeof setTimeout>): void {
    clearTimeout(timer);
    this.timers.delete(timer);
  }

  /**
   * 清理指定的间隔器
   */
  static clearInterval(interval: ReturnType<typeof setInterval>): void {
    clearInterval(interval);
    this.intervals.delete(interval);
  }

  /**
   * 移除指定的事件监听器
   */
  static removeEventListener(
    target: EventTarget,
    event: string,
    handler: EventListener,
    options?: boolean | EventListenerOptions
  ): void {
    target.removeEventListener(event, handler, options);

    const listeners = this.listeners.get(target);
    if (listeners) {
      const index = listeners.findIndex(l => l.event === event && l.handler === handler);
      if (index > -1) {
        listeners.splice(index, 1);
      }

      if (listeners.length === 0) {
        this.listeners.delete(target);
      }
    }
  }

  /**
   * 清理所有定时器
   */
  static clearAllTimers(): void {
    this.timers.forEach(timer => clearTimeout(timer));
    this.timers.clear();

    this.intervals.forEach(interval => clearInterval(interval));
    this.intervals.clear();
  }

  /**
   * 清理所有事件监听器
   */
  static clearAllEventListeners(): void {
    this.listeners.forEach((listeners, target) => {
      listeners.forEach(({ event, handler }) => {
        try {
          target.removeEventListener(event, handler);
        } catch (error) {
          // console.warn('清理事件监听器失败:', error);
          console.error('cleanup event listener failed', error);
        }
      });
    });
    this.listeners.clear();
  }

  /**
   * 全面清理所有追踪的资源
   */
  static cleanup(): void {
    this.clearAllTimers();
    this.clearAllEventListeners();
  }

  /**
   * 获取当前追踪的资源统计信息
   */
  static getStats(): {
    timers: number;
    intervals: number;
    listeners: number;
  } {
    let totalListeners = 0;
    this.listeners.forEach(listeners => {
      totalListeners += listeners.length;
    });

    return {
      timers: this.timers.size,
      intervals: this.intervals.size,
      listeners: totalListeners
    };
  }
}

/**
 * 页面可见性管理 - 在页面不可见时暂停一些操作，避免资源浪费
 */
export class VisibilityManager {
  private static callbacks: Set<(isVisible: boolean) => void> = new Set();
  private static isListening = false;

  /**
   * 添加页面可见性变化回调
   */
  static addCallback(callback: (isVisible: boolean) => void): () => void {
    this.callbacks.add(callback);

    if (!this.isListening) {
      this.startListening();
    }

    // 返回清理函数
    return () => {
      this.callbacks.delete(callback);
      if (this.callbacks.size === 0) {
        this.stopListening();
      }
    };
  }

  /**
   * 开始监听页面可见性变化
   */
  private static startListening(): void {
    const handleVisibilityChange = () => {
      const isVisible = !document.hidden;
      this.callbacks.forEach(callback => {
        try {
          callback(isVisible);
        } catch (error) {
          // console.warn('页面可见性回调执行失败:', error);
          console.error('page visibility callback execution failed', error);
        }
      });
    };

    MemoryManager.addEventListener(document, 'visibilitychange', handleVisibilityChange);
    this.isListening = true;
  }

  /**
   * 停止监听页面可见性变化
   */
  private static stopListening(): void {
    // 事件监听器会在MemoryManager.clearAllEventListeners()中被清理
    this.isListening = false;
  }

  /**
   * 获取当前页面是否可见
   */
  static isVisible(): boolean {
    return !document.hidden;
  }

  /**
   * 清理所有回调
   */
  static cleanup(): void {
    this.callbacks.clear();
    this.stopListening();
  }
}

/**
 * 在页面卸载时执行清理
 */
export function setupGlobalCleanup(): void {
  const cleanup = () => {
    MemoryManager.cleanup();
    VisibilityManager.cleanup();
  };

  // 监听页面卸载事件
  MemoryManager.addEventListener(window, 'beforeunload', cleanup);
  MemoryManager.addEventListener(window, 'unload', cleanup);

  // 监听页面隐藏事件（移动端）
  MemoryManager.addEventListener(document, 'visibilitychange', () => {
    if (document.hidden) {
      // 页面被隐藏时，执行部分清理
      const stats = MemoryManager.getStats();
      if (stats.timers > 10 || stats.intervals > 5) {
        // console.warn('检测到大量定时器，执行清理:', stats);
        console.error('detected many timers, execute cleanup', stats);
        MemoryManager.clearAllTimers();
      }
    }
  });
}

/**
 * 检测内存使用情况（如果支持）
 */
export function checkMemoryUsage(): {
  supported: boolean;
  usage?: {
    usedJSHeapSize: number;
    totalJSHeapSize: number;
    jsHeapSizeLimit: number;
    usagePercent: number;
  };
} {
  // @ts-ignore - performance.memory在某些浏览器中可用
  if (typeof performance !== 'undefined' && performance.memory) {
    // @ts-ignore
    const memory = performance.memory;
    const usagePercent = (memory.usedJSHeapSize / memory.jsHeapSizeLimit) * 100;

    return {
      supported: true,
      usage: {
        usedJSHeapSize: memory.usedJSHeapSize,
        totalJSHeapSize: memory.totalJSHeapSize,
        jsHeapSizeLimit: memory.jsHeapSizeLimit,
        usagePercent
      }
    };
  }

  return { supported: false };
}

/**
 * 内存监控和自动清理
 */
export function startMemoryMonitoring(options: {
  interval?: number;
  warningThreshold?: number;
  criticalThreshold?: number;
} = {}): () => void {
  const {
    interval = 30000, // 30秒检查一次
    warningThreshold = 70, // 70%内存使用率警告
    criticalThreshold = 85 // 85%内存使用率执行清理
  } = options;

  const monitor = () => {
    const memoryInfo = checkMemoryUsage();
    if (memoryInfo.supported && memoryInfo.usage) {
      const { usagePercent } = memoryInfo.usage;

      if (usagePercent > criticalThreshold) {
        // console.warn('内存使用率过高，执行清理:', usagePercent.toFixed(2) + '%');
        console.error('memory usage is too high, execute cleanup', usagePercent.toFixed(2) + '%');
        MemoryManager.clearAllTimers();

        // 强制垃圾回收（如果支持）
        // @ts-ignore
        if (typeof window.gc === 'function') {
          // @ts-ignore
          window.gc();
        }
      } else if (usagePercent > warningThreshold) {
        // console.warn('内存使用率较高:', usagePercent.toFixed(2) + '%');
        console.error('memory usage is high', usagePercent.toFixed(2) + '%');
      }
    }

    // 检查资源统计
    const stats = MemoryManager.getStats();
    if (stats.timers > 20 || stats.intervals > 10 || stats.listeners > 50) {
      // console.warn('检测到大量资源，建议清理:', stats);
      console.error('detected many resources, suggest cleanup', stats);
    }
  };

  const intervalId = MemoryManager.setInterval(monitor, interval);

  // 返回清理函数
  return () => {
    MemoryManager.clearInterval(intervalId);
  };
} 